#include "NodeHotAreaChangeRecorder.hpp"
#include "cybertron/network/SocketTcpClientSync.hpp"

CYBERTRON_BEGIN

NodeHotAreaChangeRecorder::NodeHotAreaChangeRecorder()
{
	mpActorsOwnedByClientPtr = std::make_shared<TrafficActorHotArea>();
	mpActorsOwnedByClient = mpActorsOwnedByClientPtr.get();

	zeroMembers();
}

NodeHotAreaChangeRecorder::~NodeHotAreaChangeRecorder()
{
	clearThis();
}

void NodeHotAreaChangeRecorder::zeroMembers()
{
	// do nothing.
}

void NodeHotAreaChangeRecorder::clearThis()
{
	mpActorsOwnedByClient->clear();
	mHotAreaIdsOwnedByClient.clear();
	mHotAreaOwnedByClient.clear();
	mHotAreaIdsSubscribed.clear();
	mHotAreaSubscribed.clear();
	mServerHotAreas.clear();
	mServerHotAreasById.clear();
	mChangesToServerHotAreas.clear();

	zeroMembers();
}

void NodeHotAreaChangeRecorder::reset()
{
	clearThis();
}

void NodeHotAreaChangeRecorder::deleteAllActors()
{
	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];

		HotArea::FromAnyAddDeleteTrafficActors& addDeleteChange = pChanges->addDeleteActors;
		std::set<int> actorIdSet = mpActorsOwnedByClient->getActorIdSet();
		for (auto it = actorIdSet.begin(); it != actorIdSet.end(); it++)
		{
			const TrafficActor& actor = mpActorsOwnedByClient->getActor(*it);

			int actorId = actor.getRuntimeId();
			if (actorId < 0)
			{
				continue;
			}

			if (pHotArea->hasActor(actorId))
			{
				pHotArea->deleteActor(actorId);

				addDeleteChange.add_deletedactorids(actorId);
			}
		}
	}

	mpActorsOwnedByClient->deleteAllActors();
}

void NodeHotAreaChangeRecorder::createActor(
	int actorId,
	HotArea::EActorType actorType,
	int assetId,
	const vec3& size,
	const vec3& position,
	const vec3& rotation)
{
	if (mpActorsOwnedByClient->hasActor(actorId))
	{
		// cannot create the same actor twice.
		return;
	}

	mpActorsOwnedByClient->createActor(actorId, actorType, assetId, size);
	mpActorsOwnedByClient->updateActorPositionRotation(actorId, position, rotation);

	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		if (!pHotArea->isInRange(position))
		{
			continue;
		}

		pHotArea->createActor(actorId, actorType, assetId, size);

		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];
		HotArea::FromAnyAddDeleteTrafficActors& addDeleteChange = pChanges->addDeleteActors;
		addDeleteChange.set_hotareaid(pHotArea->getId());
		addDeleteChange.add_addedactorids(actorId);
		addDeleteChange.add_addedtypes(actorType);
		addDeleteChange.add_addedassetids(assetId);
		addDeleteChange.add_addedpositionrotationsizes(position.x);
		addDeleteChange.add_addedpositionrotationsizes(position.y);
		addDeleteChange.add_addedpositionrotationsizes(position.z);
		addDeleteChange.add_addedpositionrotationsizes(rotation.x);
		addDeleteChange.add_addedpositionrotationsizes(rotation.y);
		addDeleteChange.add_addedpositionrotationsizes(rotation.z);
		addDeleteChange.add_addedpositionrotationsizes(size.x);
		addDeleteChange.add_addedpositionrotationsizes(size.y);
		addDeleteChange.add_addedpositionrotationsizes(size.z);
	}
}

void NodeHotAreaChangeRecorder::deleteActor(int actorId)
{
	if (!mpActorsOwnedByClient->hasActor(actorId))
	{
		// cannot delete an actor that is not owned by client
		return;
	}

	const TrafficActor& actor = mpActorsOwnedByClient->getActor(actorId);

	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		if (!pHotArea->hasActor(actorId))
		{
			continue;
		}

		pHotArea->deleteActor(actorId);

		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];
		HotArea::FromAnyAddDeleteTrafficActors& addDeleteChange = pChanges->addDeleteActors;

		addDeleteChange.set_hotareaid(pHotArea->getId());
		addDeleteChange.add_deletedactorids(actorId);
	}

	mpActorsOwnedByClient->deleteActor(actorId);
}

bool NodeHotAreaChangeRecorder::updateActorPosition(
	int actorId,
	const vec3& position)
{
	if (!mpActorsOwnedByClient->hasActor(actorId))
	{
		return false;
	}

	const TrafficActor& actor = mpActorsOwnedByClient->getActor(actorId);

	vec3 rotation = actor.getWorldRotation();

	bool res = false;
	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];

		if (pHotArea->hasActor(actorId))
		{
			if (pHotArea->isInRange(position))
			{
				HotArea::FromAnyUpdateTrafficActorPositionRotation& updateChange = pChanges->updateActorPositionRotation;

				updateChange.set_hotareaid(pHotArea->getId());
				updateChange.add_actorids(actor.getRuntimeId());
				updateChange.add_positionrotations(position.x);
				updateChange.add_positionrotations(position.y);
				updateChange.add_positionrotations(position.z);
				updateChange.add_positionrotations(rotation.x);
				updateChange.add_positionrotations(rotation.y);
				updateChange.add_positionrotations(rotation.z);
				res = true;
			}
			else
			{
				HotArea::FromAnyAddDeleteTrafficActors& deleteChange = pChanges->addDeleteActors;

				pHotArea->deleteActor(actorId);

				deleteChange.set_hotareaid(pHotArea->getId());
				deleteChange.add_deletedactorids(actor.getRuntimeId());
			}
		}
		else
		{
			if (pHotArea->isInRange(position))
			{
				pHotArea->createActor(actorId, actor.getActorType(), actor.getAssetId(), actor.getObjectSpaceSize());

				HotArea::FromAnyAddDeleteTrafficActors& addChange = pChanges->addDeleteActors;
				addChange.set_hotareaid(pHotArea->getId());
				addChange.add_addedactorids(actorId);
				addChange.add_addedtypes(actor.getActorType());
				addChange.add_addedassetids(actor.getAssetId());
				addChange.add_addedpositionrotationsizes(position.x);
				addChange.add_addedpositionrotationsizes(position.y);
				addChange.add_addedpositionrotationsizes(position.z);
				addChange.add_addedpositionrotationsizes(rotation.x);
				addChange.add_addedpositionrotationsizes(rotation.y);
				addChange.add_addedpositionrotationsizes(rotation.z);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().x);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().y);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().z);
				res = true;
			}
		}
	}

	mpActorsOwnedByClient->updateActorPosition(actorId, position);
	return res;
}

bool NodeHotAreaChangeRecorder::updateActorPositionRotation(
	int actorId,
	const vec3& position,
	const vec3& rotation)
{
	if (!mpActorsOwnedByClient->hasActor(actorId))
	{
		return false;
	}

	const TrafficActor& actor = mpActorsOwnedByClient->getActor(actorId);

	bool res = false;
	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];

		if (pHotArea->hasActor(actorId))
		{
			if (pHotArea->isInRange(position))
			{
				HotArea::FromAnyUpdateTrafficActorPositionRotation& updateChange = pChanges->updateActorPositionRotation;

				updateChange.set_hotareaid(pHotArea->getId());
				updateChange.add_actorids(actor.getRuntimeId());
				updateChange.add_positionrotations(position.x);
				updateChange.add_positionrotations(position.y);
				updateChange.add_positionrotations(position.z);
				updateChange.add_positionrotations(rotation.x);
				updateChange.add_positionrotations(rotation.y);
				updateChange.add_positionrotations(rotation.z);
				res = true;
			}
			else
			{
				HotArea::FromAnyAddDeleteTrafficActors& deleteChange = pChanges->addDeleteActors;

				pHotArea->deleteActor(actorId);

				deleteChange.set_hotareaid(pHotArea->getId());
				deleteChange.add_deletedactorids(actor.getRuntimeId());
			}
		}
		else
		{
			if (pHotArea->isInRange(position))
			{
				pHotArea->createActor(actorId, actor.getActorType(), actor.getAssetId(), actor.getObjectSpaceSize());

				HotArea::FromAnyAddDeleteTrafficActors& addChange = pChanges->addDeleteActors;
				addChange.set_hotareaid(pHotArea->getId());
				addChange.add_addedactorids(actorId);
				addChange.add_addedtypes(actor.getActorType());
				addChange.add_addedassetids(actor.getAssetId());
				addChange.add_addedpositionrotationsizes(position.x);
				addChange.add_addedpositionrotationsizes(position.y);
				addChange.add_addedpositionrotationsizes(position.z);
				addChange.add_addedpositionrotationsizes(rotation.x);
				addChange.add_addedpositionrotationsizes(rotation.y);
				addChange.add_addedpositionrotationsizes(rotation.z);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().x);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().y);
				addChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().z);
				res = true;
			}
		}
	}

	mpActorsOwnedByClient->updateActorPositionRotation(actorId, position, rotation);
	return res;
}

void NodeHotAreaChangeRecorder::updateActorFlags(
	int actorId,
	std::uint32_t flags)
{
	if (!mpActorsOwnedByClient->hasActor(actorId))
	{
		return;
	}

	const TrafficActor& actor = mpActorsOwnedByClient->getActor(actorId);

	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		if (!pHotArea->hasActor(actorId))
		{
			continue;
		}

		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];
		HotArea::FromAnyUpdateTrafficActorFlags& updateChange = pChanges->updateFlags;

		updateChange.set_hotareaid(pHotArea->getId());
		updateChange.add_actorids(actorId);
		updateChange.add_flags(flags);
	}

	mpActorsOwnedByClient->updateActorFlags(actorId, flags);
}

void NodeHotAreaChangeRecorder::updateActorCustomProperties(
	int actorId,
	google::protobuf::MessageLite &protoMsg)
{
	if (!mpActorsOwnedByClient->hasActor(actorId))
	{
		return;
	}
	size_t msgBodyLength = protoMsg.ByteSizeLong();

	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[i];
		if (!pHotArea->hasActor(actorId))
		{
			continue;
		}

		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];
		HotArea::FromAnyUpdateTrafficActorCustomProperties& updateChange = pChanges->updateCustomProperties;

		updateChange.set_hotareaid(pHotArea->getId());
		updateChange.add_actorids(actorId);
		updateChange.add_custompropertysizes((std::uint32_t)msgBodyLength);
		std::string* pData = updateChange.mutable_custompropertydatas();

		size_t oldSize = pData->size();
		pData->resize(oldSize + msgBodyLength);
		protoMsg.SerializeToArray(&pData->operator[](oldSize), (int)msgBodyLength);
	}

	mpActorsOwnedByClient->updateActorCustomProperties(actorId, protoMsg);
}

void NodeHotAreaChangeRecorder::dispatchChanges(
	std::shared_ptr<SocketBase> pSocket)
{
	if (pSocket == nullptr || pSocket->getStatus() != ESocketStatus_Connected)
	{
		return;
	}
	std::uint32_t createstamp = std::uint32_t(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) / 1000;
	for (size_t i = 0; i < mChangesToServerHotAreas.size(); ++i)
	{
		std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[i];

		if (pChanges->addDeleteActors.addedactorids_size() != 0 || pChanges->addDeleteActors.deletedactorids_size() != 0)
		{
			pChanges->addDeleteActors.set_createstamp(createstamp);
			pSocket->send(HotArea::EFromAnyAddDeleteTrafficActors, pChanges->addDeleteActors);
		}
		if (pChanges->updateActorPositionRotation.actorids_size() != 0)
		{
			pChanges->updateActorPositionRotation.set_createstamp(createstamp);
			//logInfo("dispatchChanges=====>%f,%f,%f", pChanges->updateActorPositionRotation.);
			pSocket->send(HotArea::EFromAnyUpdateTrafficActorPositionRotation, pChanges->updateActorPositionRotation);
		}
		if (pChanges->updateFlags.actorids_size() != 0)
		{
			pChanges->updateFlags.set_createstamp(createstamp);
			pSocket->send(HotArea::EFromAnyUpdateTrafficActorFlags, pChanges->updateFlags);
		}
		if (pChanges->updateCustomProperties.actorids_size() != 0)
		{
			pChanges->updateCustomProperties.set_createstamp(createstamp);
			pSocket->send(HotArea::EFromAnyUpdateTrafficActorCustomProperties, pChanges->updateCustomProperties);
		}

		pChanges->addDeleteActors.Clear();
		pChanges->updateActorPositionRotation.Clear();
		pChanges->updateFlags.Clear();
		pChanges->updateCustomProperties.Clear();
	}
}

void NodeHotAreaChangeRecorder::onHotAreaCreate(
	int hotAreaId,
	const vec3& position,
	const vec3& rotition,
	float radius)
{
	if (mServerHotAreasById.find(hotAreaId) != mServerHotAreasById.end())
	{
		// cannot create the same hot area twice!
		return;
	}

	std::shared_ptr<TrafficActorHotArea> pHotArea = std::make_shared<TrafficActorHotArea>();
	std::shared_ptr<HotAreaChanges> pChanges = std::make_shared<HotAreaChanges>();
	pHotArea->create(hotAreaId, position, rotition, radius);

	mServerHotAreasById[hotAreaId] = pHotArea;
	mServerHotAreas.push_back(pHotArea);
	mChangesToServerHotAreas.push_back(pChanges);

	HotArea::FromAnyAddDeleteTrafficActors& addDeleteChange = pChanges->addDeleteActors;
	HotArea::FromAnyUpdateTrafficActorPositionRotation& updateChange = pChanges->updateActorPositionRotation;

	addDeleteChange.set_hotareaid(hotAreaId);
	updateChange.set_hotareaid(hotAreaId);

	std::set<int> actorIdSet = mpActorsOwnedByClient->getActorIdSet();
	for (auto it = actorIdSet.begin(); it != actorIdSet.end(); it++)
	{
		const TrafficActor& actor = mpActorsOwnedByClient->getActor(*it);
		int actorId = actor.getRuntimeId();
		if (actorId < 0)
		{
			continue;
		}

		if (pHotArea->isInRange(actor.getWorldPosition()))
		{
			// add
			addDeleteChange.set_hotareaid(pHotArea->getId());
			addDeleteChange.add_addedactorids(actorId);
			addDeleteChange.add_addedtypes(actor.getActorType());
			addDeleteChange.add_addedassetids(actor.getAssetId());
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().x);
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().y);
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().z);
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().x);
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().y);
			addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().z);
			addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().x);
			addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().y);
			addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().z);

			pHotArea->createActor(actorId, actor.getActorType(), actor.getAssetId(), actor.getObjectSpaceSize());
		}
	}
}

void NodeHotAreaChangeRecorder::onHotAreaUpdate(
	int hotAreaId,
	const vec3& position)
{
	size_t hotAreaIndex = (size_t)-1;
	for (size_t i = 0; i < mServerHotAreas.size(); ++i)
	{
		if (mServerHotAreas[i]->getId() == hotAreaId)
		{
			hotAreaIndex = i;
			break;
		}
	}
	if (hotAreaIndex == (size_t)-1)
	{
		return;
	}

	std::shared_ptr<TrafficActorHotArea> pHotArea = mServerHotAreas[hotAreaIndex];
	std::shared_ptr<HotAreaChanges> pChanges = mChangesToServerHotAreas[hotAreaIndex];

	HotArea::FromAnyAddDeleteTrafficActors& addDeleteChange = pChanges->addDeleteActors;
	HotArea::FromAnyUpdateTrafficActorPositionRotation& updateChange = pChanges->updateActorPositionRotation;

	addDeleteChange.set_hotareaid(hotAreaId);
	updateChange.set_hotareaid(hotAreaId);

	vec3 positionOld = pHotArea->getPosition();
	vec3 positionNew = position;

	pHotArea->setPosition(position);

	std::set<int> actorIdSet = mpActorsOwnedByClient->getActorIdSet();
	for (auto it = actorIdSet.begin(); it != actorIdSet.end(); it++)
	{
		const TrafficActor& actor = mpActorsOwnedByClient->getActor(*it);
		int actorId = actor.getRuntimeId();
		if (actorId < 0)
		{
			continue;
		}

		if (pHotArea->hasActor(actorId))
		{
			if (!pHotArea->isInRange(actor.getWorldPosition()))
			{
				// delete
				pHotArea->deleteActor(actorId);
				addDeleteChange.add_deletedactorids(actorId);
			}
		}
		else
		{
			if (pHotArea->isInRange(actor.getWorldPosition()))
			{
				pHotArea->createActor(actorId, actor.getActorType(), actor.getAssetId(), actor.getObjectSpaceSize());

				// add
				addDeleteChange.set_hotareaid(pHotArea->getId());
				addDeleteChange.add_addedactorids(actorId);
				addDeleteChange.add_addedtypes(actor.getActorType());
				addDeleteChange.add_addedassetids(actor.getAssetId());
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().x);
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().y);
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldPosition().z);
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().x);
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().y);
				addDeleteChange.add_addedpositionrotationsizes(actor.getWorldRotation().z);
				addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().x);
				addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().y);
				addDeleteChange.add_addedpositionrotationsizes(actor.getObjectSpaceSize().z);
			}
		}
	}
}

void NodeHotAreaChangeRecorder::onHotAreaDelete(
	int hotAreaId)
{
	{
		size_t hotAreaIndex = (size_t)-1;
		for (size_t i = 0; i < mServerHotAreas.size(); ++i)
		{
			if (mServerHotAreas[i]->getId() == hotAreaId)
			{
				hotAreaIndex = i;
				break;
			}
		}
		if (hotAreaIndex != (size_t)-1)
		{
			mServerHotAreas.erase(mServerHotAreas.begin() + hotAreaIndex);
			mChangesToServerHotAreas.erase(mChangesToServerHotAreas.begin() + hotAreaIndex);
			mServerHotAreasById.erase(mServerHotAreasById.find(hotAreaId));
		}
	}

	{
		size_t hotAreaIndex = (size_t)-1;
		for (size_t i = 0; i < mHotAreaOwnedByClient.size(); ++i)
		{
			if (mHotAreaOwnedByClient[i]->getId() == hotAreaId)
			{
				hotAreaIndex = i;
				break;
			}
		}
		if (hotAreaIndex != (size_t)-1)
		{
			mHotAreaIdsOwnedByClient.erase(mHotAreaIdsOwnedByClient.begin() + hotAreaIndex);
			mHotAreaOwnedByClient.erase(mHotAreaOwnedByClient.begin() + hotAreaIndex);
		}
	}

	{
		size_t hotAreaIndex = (size_t)-1;
		for (size_t i = 0; i < mHotAreaSubscribed.size(); ++i)
		{
			if (mHotAreaSubscribed[i]->getId() == hotAreaId)
			{
				hotAreaIndex = i;
				break;
			}
		}
		if (hotAreaIndex != (size_t)-1)
		{
			mHotAreaIdsSubscribed.erase(mHotAreaIdsSubscribed.begin() + hotAreaIndex);
			mHotAreaSubscribed.erase(mHotAreaSubscribed.begin() + hotAreaIndex);
		}
	}
}

bool NodeHotAreaChangeRecorder::getHotAreaOwnedByClient(int hotAreaId) const
{
	return std::find(mHotAreaIdsOwnedByClient.begin(), mHotAreaIdsOwnedByClient.end(), hotAreaId) != mHotAreaIdsOwnedByClient.end();
}

void NodeHotAreaChangeRecorder::setHotAreaOwnedByClient(int hotAreaId, bool ownedByClient)
{
	auto it = std::find(
		mHotAreaIdsOwnedByClient.begin(),
		mHotAreaIdsOwnedByClient.end(),
		hotAreaId);

	if (ownedByClient)
	{
		if (it != mHotAreaIdsOwnedByClient.end())
		{
			return;
		}

		auto pHotArea = findHotArea(hotAreaId);
		if (pHotArea == nullptr)
		{
			return;
		}

		mHotAreaIdsOwnedByClient.push_back(hotAreaId);
		mHotAreaOwnedByClient.push_back(pHotArea);
	}
	else
	{
		if (it == mHotAreaIdsOwnedByClient.end())
		{
			return;
		}

		size_t index = (size_t)(it - mHotAreaIdsOwnedByClient.begin());

		mHotAreaIdsOwnedByClient.erase(mHotAreaIdsOwnedByClient.begin() + index);
		mHotAreaOwnedByClient.erase(mHotAreaOwnedByClient.begin() + index);
	}
}

bool NodeHotAreaChangeRecorder::getHotAreaSubscribed(int hotAreaId) const
{
	return std::find(mHotAreaIdsSubscribed.begin(), mHotAreaIdsSubscribed.end(), hotAreaId) != mHotAreaIdsSubscribed.end();
}

void NodeHotAreaChangeRecorder::setHotAreaSubscribed(int hotAreaId, bool subscribed)
{
	auto it = std::find(
		mHotAreaIdsSubscribed.begin(),
		mHotAreaIdsSubscribed.end(),
		hotAreaId);

	if (subscribed)
	{
		if (it != mHotAreaIdsSubscribed.end())
		{
			return;
		}

		auto pHotArea = findHotArea(hotAreaId);
		if (pHotArea == nullptr)
		{
			return;
		}

		mHotAreaIdsSubscribed.push_back(hotAreaId);
		mHotAreaSubscribed.push_back(pHotArea);
	}
	else
	{
		if (it == mHotAreaIdsSubscribed.end())
		{
			return;
		}

		size_t index = (size_t)(it - mHotAreaIdsSubscribed.begin());

		mHotAreaIdsSubscribed.erase(mHotAreaIdsSubscribed.begin() + index);
		mHotAreaSubscribed.erase(mHotAreaSubscribed.begin() + index);
	}
}

const std::vector<std::shared_ptr<TrafficActorHotArea>>& 
NodeHotAreaChangeRecorder::getSubscribedHotAreas() const
{
	return mHotAreaSubscribed;
}

const std::vector<std::shared_ptr<TrafficActorHotArea>>&
NodeHotAreaChangeRecorder::getHotAreas() const
{
	return mServerHotAreas;
}

std::shared_ptr<TrafficActorHotArea> 
NodeHotAreaChangeRecorder::getActorsOwnedByClient() const
{
	return mpActorsOwnedByClientPtr;
}

std::shared_ptr<TrafficActorHotArea> NodeHotAreaChangeRecorder::findHotArea(int id)
{
	auto it = mServerHotAreasById.find(id);
	if (it == mServerHotAreasById.end())
	{
		return nullptr;
	}

	return (*it).second;
}

CYBERTRON_END
